package org.funtester.performance.books.chapter07.section3;

import org.funtester.performance.books.chapter03.section3.ThreadTask;
import org.funtester.performance.books.chapter03.section4.TaskExecutor;
import org.funtester.performance.books.chapter04.section3.RandomTool;
import org.funtester.performance.books.chapter06.section2.MySqlBase;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 */
public class RedisExpireCase {

    public static void main(String[] args) throws InterruptedException {
        String redisHost = "127.0.0.1";// Redis服务端IP
        int redisPort = 6379;// Redis服务端端口号
        String redisPrefix = "uid_";// Redis键前缀
        JedisPoolConfig config = new JedisPoolConfig();// 连接池配置对象
        config.setMaxTotal(100);// 设置最大连接数
        config.setMaxIdle(30);// 设置最大空闲连接数
        config.setMinIdle(10);// 设置最小空闲连接数
        config.setTestOnBorrow(true);// 设置当从连接池获取连接时，是否检查连接有效性
        config.setTestOnReturn(true);// 设置当向连接池归还连接时，是否检查连接有效性
        config.setBlockWhenExhausted(true);// 设置当连接池连接耗尽时，是否阻塞等待
        config.setMaxWaitMillis(3000);// 设置等待连接池获取连接的最大等待时间（毫秒）
        JedisPool jedisPool = new JedisPool(config, redisHost, redisPort);// 创建Jedis连接池对象
        String url = "jdbc:mysql://127.0.0.1:3306/funtester";// MySQL服务端地址
        String user = "root";// MySQL用户名
        String password = "funtester";// MySQL密码
        int totalNum = 1000;// 总执行次数
        int threadNum = 8;// 线程数
        int rumpUpTime = 20;// Rump-Up运行时间
        List<ThreadTask> tasks = new ArrayList<>();// 任务集合
        AtomicInteger threadIndex = new AtomicInteger();// 线程索引
        String selectFormat = "select id,name,age,address from user where id = %d;";// 查询语句,根据用户ID查询用户信息
        List<Integer> userIdsTotal = new ArrayList<>();// 用户ID集合
        for (int i = 100000; i < 200000; i++) {// 生成100000-200000的用户ID
            userIdsTotal.add(i);// 添加到用户ID集合
        }
        for (int i = 0; i < threadNum; i++) {
            ThreadTask threadTask = new ThreadTask() {

                /**
                 * 数据库操作基础类
                 */
                MySqlBase base;

                /**
                 * 用户ID集合
                 */
                List<Integer> userIds = new ArrayList<>();

                /**
                 * 请求比例控制计数
                 */
                int ratio;

                @Override
                public void before() {
                    super.before();// 调用父类的方法
                    base = new MySqlBase(url, user, password);// 创建数据库操作基础类
                    try {
                        base.init();// 初始化资源
                    } catch (SQLException e) {
                        throw new RuntimeException(e);// 抛出运行时异常
                    }
                    int index = threadIndex.getAndIncrement();// 获取线程索引
                    userIdsTotal.forEach(x -> {// 遍历用户ID集合
                        if (x % threadNum == index) {// 如果用户ID对线程数取余等于线程索引
                            userIds.add(x);// 添加到用户ID集合
                        }
                    });

                }

                @Override
                public void test() {
                    Integer userId = RandomTool.getRandomElement(userIds);// 模拟从用户模型中获取用户ID
                    String key = redisPrefix + userId;// 拼接Redis键
                    User user = null;// 用户对象
                    try (Jedis jedis = jedisPool.getResource()) {// 获取Jedis对象
                        String userInfo = jedis.get(key);// 查询Redis中的用户信息
                        if (userInfo == null) {// 如果没有数据,则从数据库中查询
                            String querySql = String.format(selectFormat, userId);// 格式化 SQL 语句
                            try (ResultSet resultSet = base.statement.executeQuery(querySql)) {// 执行查询语句
                                if (resultSet.next()) {// 如果有数据
                                    user = new User(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getInt("age"), resultSet.getString("address"));// 创建用户对象
                                    String set = jedis.set(key, user.toString());// 更新Redis中的用户信息
                                    if (set.equals("OK")) {
                                        //此处统计成功次数,为了简化用例,省去了
                                    }
                                }
                            } catch (SQLException e) {
                                //此处统计失败次数,为了简化用例,省去了
                            }
                        }
                        user = User.init(userInfo);// 初始化用户信息
                    }
                }
            };
            threadTask.totalNum = totalNum;// 设置执行次数
            threadTask.costTime = new ArrayList<>(totalNum);// 设置任务的执行时间集合,设置容量,避免频繁扩容
            tasks.add(threadTask);// 添加任务到任务集合
        }
        TaskExecutor taskExecutor = new TaskExecutor(tasks, "用户更新地址查询验证", rumpUpTime);
        taskExecutor.start();// 启动任务执行器
    }

}
